package cn.ztuo.bitrade.controller;

import cn.ztuo.bitrade.constant.BooleanEnum;
import cn.ztuo.bitrade.constant.TransactionType;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.entity.transform.AuthMember;
import cn.ztuo.bitrade.service.*;
import cn.ztuo.bitrade.util.BigDecimalUtils;
import cn.ztuo.bitrade.util.Md5;
import cn.ztuo.bitrade.util.MessageResult;
import cn.ztuo.bitrade.vo.EmptionRecrodVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

import static cn.ztuo.bitrade.constant.SysConstant.SESSION_MEMBER;

@RequestMapping("odfieo")
@RestController
@Slf4j
public class IeoOdfController {

    private static final String CARD="ODFc6HgWvT8VwBYDeJ12BkzFnGHLnYdau2Ep";
    @Autowired
    private IeoOdfService ieoEmptionService;

    @Autowired
    private IeoOdfrecordService ieoOdfrecordService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private MemberWalletService walletService;

    @Autowired
    private LocaleMessageSourceService msService;

    @Autowired
    private BourseProductManagerService productManagerService;

    @Autowired
    private RelationService relationService;

    @Autowired
    private SysCfService sysCfService;

    @Autowired
    private IeoMentService ieoMentService;

    @Autowired
    private MemberTransactionService transactionService;
    private static final int DEFAULT_DIV_SCALE = 4;

    /**
     * 创建募集订单
     * @param authMember
     * @param id
     * @param number
     * @param jyPassword
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "add-ieo", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public MessageResult add_record(
            @SessionAttribute(SESSION_MEMBER) AuthMember authMember,
            Long id,
            BigDecimal number,
            String jyPassword
    ) {
        //判断该产品是否关闭
        BourseProductManager productManager = productManagerService.getByProductCode("0400");
        if(productManager.getStatus()==0){
            return MessageResult.error(400, msService.getMessage("PRODUCT_CLOSE"));
        }
        if (jyPassword == null || jyPassword.equals("")) {
            return MessageResult.error("安全密码不能为空");
        }
        Member member = memberService.findOne(authMember.getId());
        if (member.getTransactionStatus().equals(BooleanEnum.IS_FALSE)) {
            return MessageResult.error("您当前账户已禁用，请联系客服！");
        }
        Boolean success = relationService.findActivation(member.getId());
        if(!success) return MessageResult.error(400,"账号未激活");
        //验证交易密码
        String mbPassword = member.getPassword();
        try {
            if (!Md5.md5Digest(jyPassword + member.getSalt()).toLowerCase().equals(mbPassword))
                return MessageResult.error(400, "安全密码错误");
        }catch (Exception e){
            e.printStackTrace();
        }
        IeoOdf ieo = ieoEmptionService.findById(id);
        //验证状态 1=进行中 2=已结束
        if (ieo.getStatus() == 3) return MessageResult.error(400, "认购未开启");
        if (ieo.getStatus() == 2) return MessageResult.error(400, "认购已结束");
        //如果开启判断时间是否开始
        Date date = new Date();
        Timestamp timestamp = new Timestamp(date.getTime());
        //验证如果已经购买不能在购买
        ArrayList<Integer> types = new ArrayList<>();
        //计算数量
        BigDecimal account = BigDecimal.ZERO;
        String status = "1";
        number = number.abs();
        BigDecimal price = ieo.getRatio();
        if(ieo.getType()==4) {
            BigDecimal limitNumber  = memberService.ieoRemaining(member.getId());
            if(number.compareTo(limitNumber)==1) return MessageResult.error(400, "超过认购限额"+limitNumber);
            account = BigDecimalUtils.mulRound(number, price, DEFAULT_DIV_SCALE);
            status  = "2";//认购类型4直接结束
        }else{
            //判断已抢购类型，1，2，3类型只能买一次，4可以买多次
            number = ieo.getLimitAmount();
            types.add(ieo.getType());
            List<Long> ieorecord =  ieoOdfrecordService.selectTypes(member.getId(),types);
            if(ieorecord.size()>0) return  MessageResult.error(400, "认购已上限");
            //如果类型是3，判断社区节点个数，如果达到要求优惠价格
            if(ieo.getType()==3){
                //获取社区节点个数,如果达到条件，获取优惠价格
                List<Member> membersAll = memberService.findAllByParentsLike(String.valueOf(member.getId()));
                Integer childs = 0;
                for(Member memberpp:membersAll) {
                    if(relationService.findActivation(memberpp.getId())) {
                        ++childs;
                    }
                    if(childs>1000)
                        break;
                }
                if(childs<300)
                    return MessageResult.error(400, "当前账户无认购资格");

                if(childs >=300 )
                    price = new BigDecimal("0.3");

                if(childs>=500)
                    price = new BigDecimal("0.25");

                if(childs>=1000)
                    price = new BigDecimal("0.2");
//                List<IeoMent> ieoMents = ieoMentService.findAll();
//                for(IeoMent ment:ieoMents){
//                    if(childs>=ment.getNumber()){
//                        price = ment.getPrice();
//                        break;
//                    }
//                }
            }
            account = BigDecimalUtils.mulRound(ieo.getLimitAmount(), price, DEFAULT_DIV_SCALE);
        }
        MemberWallet memberWallet = walletService.findByCoinUnitAndMemberId(ieo.getBuyCoin(), authMember.getId());
        if (!BigDecimalUtils.compare(memberWallet.getBalance(), account)) return MessageResult.error(400, "账户资产不足,需要"+account.toString()+"U");
        int isSuccess = 0;
        BigDecimal numberTypeThree = BigDecimal.ZERO;
        if(ieo.getType()==4) {
            //如果类型是扣除募集币种，增加认购币种
            try {
                isSuccess = ieoEmptionService.subAmount(number, ieo, member.getId());
                //创建消费记录
                MemberTransaction transaction = new MemberTransaction();
                transaction.setAmount(number);
                transaction.setSymbol(ieo.getCoin());
                transaction.setAddress("");
                transaction.setMemberId(member.getId());
                transaction.setType(TransactionType.IEOBUY);
                transaction.setFee(BigDecimal.ZERO);
                transaction.setCreateTime(new Date());
                transaction.setRemark("公募认购");

                MemberWallet odfWallet2 = walletService.findByCoinUnitAndMemberId(ieo.getCoin(),member.getId());
                transaction.setFromAddress(odfWallet2.getAddress());
                transaction.setToAddress(CARD);
                transaction.setStatus(3);

                transactionService.save(transaction);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            //
            ieoEmptionService.subAmount(ieo.getId(), ieo.getLimitAmount());
            //如果是其他类型，直接扣除币种不增加
            isSuccess = walletService.deductBalance(memberWallet,account);
            //如果类型是IEO类型是3直接释放一部分
            if(ieo.getType()==3) {
                SysCf ieo3 = sysCfService.configOneCname("ieo3");
                String[] config3 = ieo3.getValue().split(",");
                HashMap<Integer, BigDecimal> map3 = new HashMap<>();
                map3.put(1, new BigDecimal(config3[0]));
                numberTypeThree = BigDecimalUtils.mul(ieo.getLimitAmount(), map3.get(1));
                MemberWallet walletto = walletService.findByCoinUnitAndMemberId(ieo.getCoin(), member.getId());
                walletService.increaseBalance(walletto.getId(), numberTypeThree);
                //创建消费记录
                MemberTransaction transaction = new MemberTransaction();
                transaction.setAmount(numberTypeThree);
                transaction.setSymbol(ieo.getCoin());
                transaction.setAddress("");
                transaction.setMemberId(member.getId());
                transaction.setType(TransactionType.IEOSHI);
                transaction.setFee(BigDecimal.ZERO);
                transaction.setCreateTime(new Date());
                transaction.setRemark("公募释放");
                MemberWallet odfWallet2 = walletService.findByCoinUnitAndMemberId(ieo.getCoin(),member.getId());
                transaction.setFromAddress(CARD);
                transaction.setToAddress(odfWallet2.getAddress());
                transaction.setStatus(4);
                transactionService.save(transaction);
            }
            if(ieo.getType()==2) {
                SysCf ieo2 = sysCfService.configOneCname("ieo2");
                String[] config2 = ieo2.getValue().split(",");
                HashMap<Integer, BigDecimal> map3 = new HashMap<>();
                map3.put(1, new BigDecimal(config2[0]));
                numberTypeThree = BigDecimalUtils.mul(ieo.getLimitAmount(), map3.get(1));
                MemberWallet walletto = walletService.findByCoinUnitAndMemberId(ieo.getCoin(), member.getId());
                walletService.increaseBalance(walletto.getId(), numberTypeThree);
                //创建消费记录
                MemberTransaction transaction = new MemberTransaction();
                transaction.setAmount(numberTypeThree);
                transaction.setSymbol(ieo.getCoin());
                transaction.setAddress("");
                transaction.setMemberId(member.getId());
                transaction.setType(TransactionType.IEOSHI);
                transaction.setFee(BigDecimal.ZERO);
                transaction.setCreateTime(new Date());
                transaction.setRemark("公募释放");
                MemberWallet odfWallet2 = walletService.findByCoinUnitAndMemberId(ieo.getCoin(),member.getId());
                transaction.setFromAddress(CARD);
                transaction.setToAddress(odfWallet2.getAddress());
                transaction.setStatus(4);
                transactionService.save(transaction);
            }
        }
        if (isSuccess > 0) {
            BigDecimal bg = BigDecimal.ZERO;
            if(ieo.getType()==4) {
                bg =   ieo.getRemaining().subtract(number);
            }else{
                bg =  ieo.getRemaining().subtract(ieo.getLimitAmount());
            }
            if(bg.compareTo(BigDecimal.ZERO)==0){
                ieo.setStatus(2);
                ieo.setRemaining(BigDecimal.ZERO);
                ieoEmptionService.save(ieo);
            }
            //创建消费记录
            MemberTransaction transaction = new MemberTransaction();
            transaction.setAmount(account.negate());
            transaction.setSymbol(ieo.getBuyCoin());
            transaction.setAddress("");
            transaction.setMemberId(member.getId());
            transaction.setType(TransactionType.IEOBUY);
            transaction.setFee(BigDecimal.ZERO);
            transaction.setCreateTime(new Date());
            transaction.setRemark("公募认购");
            MemberWallet odfWallet2 = walletService.findByCoinUnitAndMemberId(ieo.getBuyCoin(),member.getId());
            transaction.setFromAddress(odfWallet2.getAddress());
            transaction.setToAddress(CARD);
            transaction.setStatus(3);
            transactionService.save(transaction);
            //如果是锁仓释放的IEO，获取结束时间
            Date  endTime  = new Date();
            Calendar instance = Calendar.getInstance();
            if(ieo.getType()!=4){
                instance.setTime(endTime);
                instance.add(instance.DATE,ieo.getDay());
                endTime = instance.getTime();
            }
            //封装募集记录
            IeoOdfrecord order = new IeoOdfrecord();
            order.setUserId(member.getId());
            order.setUserName(member.getUsername());
            order.setUserMobile(member.getMobilePhone());
            order.setIeoName(ieo.getName());
            order.setSaleCoin(ieo.getCoin());
            order.setSaleAmount(ieo.getAmount());
            order.setRaiseCoin(ieo.getBuyCoin());
            order.setRatio(price);
            order.setStartTime(ieo.getCreateTime());
            order.setEndTime(ieo.getCreateTime());
            order.setStatus(status);
            order.setReceiveAmount(number);
            order.setPayAmount(BigDecimalUtils.sub(number,numberTypeThree));
            order.setExpectTime(endTime);
            order.setCreateTime(timestamp);
            order.setPicView(ieo.getPicView());
            order.setIeoId(ieo.getId());
            order.setType(ieo.getType());
            order.setDay(ieo.getDay());
            IeoOdfrecord insetRecord = ieoOdfrecordService.save(order);
            if (insetRecord.getId() > 0) {
                return MessageResult.success("认购成功");
            } else {
                return MessageResult.error(400, "认购失败");
            }
        } else {
            return MessageResult.error(400, "认购失败");
        }
    }
    /**
     * 查询个人ODFIEO订单记录
     * @param authMember
     * @param startTime
     * @param endTime
     * @param saleCoin
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "order-ieo", method = RequestMethod.POST)
    public MessageResult order(
            @SessionAttribute(SESSION_MEMBER) AuthMember authMember,
            @RequestParam(value = "startTime", defaultValue = "") String startTime,
            @RequestParam(value = "endTime", defaultValue = "") String endTime,
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            String saleCoin) throws Exception {
        EmptionRecrodVO emptionRecrodVO = new EmptionRecrodVO();
        emptionRecrodVO.setUserId(authMember.getId());
        emptionRecrodVO.setPageNum(pageNum);
        emptionRecrodVO.setPageSize(pageSize);
        if (startTime != null && !startTime.equals("") && endTime != null && !endTime.equals("")) {
            SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String startDate = simple.format(new Date(toLong(startTime)));
            String EndDate = simple.format(new Date(toLong(endTime)));
            emptionRecrodVO.setStartTime(startDate);
            emptionRecrodVO.setEndTime(EndDate);
        }
        if (saleCoin != null && !saleCoin.equals("")) emptionRecrodVO.setSaleCoin(saleCoin);
        Page<IeoOdfrecord> result = ieoOdfrecordService.getByPage(emptionRecrodVO);
        return MessageResult.getSuccessInstance("成功", result);
    }

    /**
     * 获取用户认购限额
     * @param authMember
     * @return
     */
    @PostMapping(value = "ieoLimit")
    public MessageResult ieoLimit(@SessionAttribute(SESSION_MEMBER) AuthMember authMember){
        Boolean is = relationService.findActivation(authMember.getId());
        HashMap<Object, Object> object = new HashMap<>();
        if(is){
            object.put("status",1);
            object.put("limit",memberService.ieoQuoda(authMember.getId()));
            object.put("userlimit",memberService.ieoRemaining(authMember.getId()));
        }else{
            object.put("status",0);
            object.put("limit",BigDecimal.ZERO);
            object.put("userlimit",BigDecimal.ZERO);
        }
        return MessageResult.getSuccessInstance("成功",object);
    }
    /**
     * 结算1-3类型的IEO
     */
    @Scheduled(cron = "0 5 0 * * ?")
    @Transactional(rollbackFor = Exception.class)
    public String Automatic(){
        //获取有类型不为4没有结束的IEO订单
        try {
            SysCf configto = sysCfService.configOneCname("ieoopen");
            if (configto.getValue().equals("2")) {
                log.info("释放认购收益未开启");
                return "释放认购收益未开启";
            }
            List<IeoOdfrecord> infos = ieoOdfrecordService.findAllByTypeNotAndStatus(4, "1");
            infos.forEach(info -> {
                HashMap<Integer, BigDecimal> map = new HashMap<>();
                switch (info.getType()) {
                    case 1:
                        //结算类型为1的IEO
                        SysCf ieo1 = sysCfService.configOneCname("ieo1");
                        String[] config = ieo1.getValue().split(",");
                        HashMap<Integer, BigDecimal> map1 = new HashMap<>();
                        map1.put(365, new BigDecimal(config[0]));
                        map1.put(730, new BigDecimal(config[1]));
                        map1.put(1095, new BigDecimal(config[2]));
                        map = map1;
                        break;
                    case 2:
                        //结算类型为2的IEO
                        SysCf ieo2 = sysCfService.configOneCname("ieo2");
                        String[] config2 = ieo2.getValue().split(",");
                        HashMap<Integer, BigDecimal> map2 = new HashMap<>();
                        map2.put(90, new BigDecimal(config2[1]));
                        map2.put(150, new BigDecimal(config2[2]));
                        map2.put(270, new BigDecimal(config2[3]));
                        map = map2;
                        break;
                    case 3:
                        //结算类型为3的IEO
                        SysCf ieo3 = sysCfService.configOneCname("ieo3");
                        String[] config3 = ieo3.getValue().split(",");
                        HashMap<Integer, BigDecimal> map3 = new HashMap<>();
                        map3.put(1, new BigDecimal(config3[1]));
                        map = map3;
                        break;
                }
                BigDecimal numbers = BigDecimal.ZERO;
                BigDecimal sy = BigDecimal.ZERO;
                if(info.getType()!=3) {
                    if (map.containsKey(info.getNowDay())) {
                        //获取收益 ReceiveAmount 总认购数量不消减
                        numbers = BigDecimalUtils.mul(info.getReceiveAmount(), map.get(info.getNowDay()));
                        if(numbers.compareTo(info.getPayAmount())>1){
                            numbers = info.getPayAmount();
                        }
                        //增加收益
                        MemberWallet wallet = walletService.findByCoinUnitAndMemberId(info.getSaleCoin(), info.getUserId());
                        walletService.increaseBalance(wallet.getId(), numbers);
                        sy = BigDecimalUtils.sub(info.getPayAmount(), numbers);
                        info.setPayAmount(sy);
                    }
                }else{
                    //IEO类型为3 单独处理，获取收益 ReceiveAmount 总认购数量不消减
                    //获取除立即释放之后剩余的数量，平均分配100天
                    BigDecimal number = BigDecimalUtils.mul(info.getReceiveAmount(), map.get(1));  //剩余的总数量
                    //每天收益数量
                     numbers = BigDecimalUtils.div(number,new BigDecimal(info.getDay()));
                    //增加收益
                    MemberWallet wallet = walletService.findByCoinUnitAndMemberId(info.getSaleCoin(), info.getUserId());
                    walletService.increaseBalance(wallet.getId(), numbers);
                    sy = BigDecimalUtils.sub(info.getPayAmount(), numbers);
                    info.setPayAmount(sy);
                }
                int days = info.getNowDay()+1;
                info.setNowDay(days);
                if (days > info.getDay()) {
                    info.setStatus("2");
                }
                ieoOdfrecordService.save(info);
                map.clear();
                if(numbers.compareTo(BigDecimal.ZERO)==1) {
                    //创建消费记录
                    MemberTransaction transaction = new MemberTransaction();
                    transaction.setAmount(numbers);
                    transaction.setSymbol(info.getSaleCoin());
                    transaction.setAddress("");
                    transaction.setMemberId(info.getUserId());
                    transaction.setType(TransactionType.IEOSHI);
                    transaction.setFee(BigDecimal.ZERO);
                    transaction.setCreateTime(new Date());
                    transaction.setRemark("公募释放");
                    MemberWallet odfWallet2 = walletService.findByCoinUnitAndMemberId(info.getSaleCoin(),info.getUserId());
                    transaction.setFromAddress(CARD);
                    transaction.setToAddress(odfWallet2.getAddress());
                    transaction.setStatus(4);
                    transactionService.save(transaction);
                }
            });
        }catch (Exception e){
            e.printStackTrace();
        }
        return "认购收益释放结束";
    }

    /**
     * 格式转换
     * @param obj
     * @return
     */
    private long toLong(String obj) {
        try {
            return Long.parseLong(obj);
        } catch (Exception e) {
        }
        return 0;
    }
}
